package com.ss.spider.system.organization.service.impl;

import com.ss.enums.StatusEnum;
import com.ss.exception.ServiceException;
import com.ss.service.AbstractCWServiceImpl;
import com.ss.spider.system.department.mapper.DepartmentMapper;
import com.ss.spider.system.department.model.Department;
import com.ss.spider.system.organization.mapper.OrganizationMapper;
import com.ss.spider.system.organization.model.Organization;
import com.ss.spider.system.organization.service.OrganizationService;
import com.ss.spider.system.sequence.model.AppSequence;
import com.ss.spider.system.sequence.model.SysSeqEnum;
import com.ss.spider.system.sequence.service.AppSequenceService;
import com.ss.tools.DateUtils;
import com.ss.tools.UUIDUtils;
import com.github.pagehelper.PageHelper;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;


@Service("organizationService")
public class OrganizationServiceImpl
        extends AbstractCWServiceImpl<Organization>
        implements OrganizationService<Organization> {

    private static final String ORG_SEQ_CODE = SysSeqEnum.ORG_ID_SEQ.getCode();


    @Autowired
    private OrganizationMapper organizationMapper;


    @Autowired
    private DepartmentMapper departmentMapper;


    @Autowired
    @Qualifier("appSequenceService")
    private AppSequenceService<AppSequence> appSequenceService;

    @Override
    public String getNewOrgId() throws ServiceException {
        return UUIDUtils.getUUID();
    }

    @Override
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public List<Organization> pages(Organization org, int pageIndex, int pageSize) {
        PageHelper.startPage(pageIndex, pageSize);
        return this.organizationMapper.pages(org);
    }

    @Override
    @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
    public List<Organization> list(Organization org) {
        return this.organizationMapper.list(org);
    }

    @Override
    @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
    public List<Organization> gets(Map<String, Object> args) {
        return this.organizationMapper.gets(args);
    }

    @Override
    @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
    public Organization get(final String orgId) {
        return get(new HashMap<String, Object>() {

        });
    }


    private Organization get(Map<String, Object> params) {
        List<Organization> list = gets(params);
        return CollectionUtils.isEmpty(list) ? null : (Organization) list.get(0);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public String save(final Organization entity) throws ServiceException {
        if (get(new HashMap<String, Object>(1) {
        }) != null) {

            throw new ServiceException("单位编号[" + entity.getOrgCode() + "]已存在");
        }

        if (get(new HashMap<String, Object>(1) {
        }) != null) {

            throw new ServiceException("单位名称[" + entity.getOrgCname() + "]已存在");
        }

        entity.setOrgId(getNewOrgId());
        try {
            if (StringUtils.hasText(entity.getParentId())) {
                Organization parent = (Organization) this.mapper.selectOne(new Organization() {

                });
                entity.setDeparth(parent.getDeparth() + "|" + entity.getOrgId());
            } else {
                Organization org = new Organization();
                org.setParentId("-1");
                List<Organization> roots = list(org);
                if (CollectionUtils.isNotEmpty(roots)) {
                    throw new ServiceException("系统只能存在一个顶级单位");
                }
                entity.setDeparth(entity.getOrgId());
            }

            this.organizationMapper.save(entity);
        } catch (Exception e) {
            this.logger.error("新增组织结构失败，原因：", e);
            if (e instanceof ServiceException) {
                throw e;
            }
            throw new ServiceException("新增组织结构失败", e);
        }

        return entity.getOrgId();
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public int update(final Organization entity) throws ServiceException {
        Organization preOrgan = get(new HashMap<String, Object>(1) {

        });

        if (preOrgan != null && !preOrgan.getOrgId().equals(entity.getOrgId())) {
            throw new ServiceException("单位编号[" + entity.getOrgCode() + "]已存在");
        }

        preOrgan = get(new HashMap<String, Object>(1) {

        });

        if (preOrgan != null && !preOrgan.getOrgId().equals(entity.getOrgId())) {
            throw new ServiceException("单位名称[" + entity.getOrgCname() + "]已存在");
        }

        if (StringUtils.hasText(entity.getParentId())) {
            Organization parent = (Organization) this.mapper.selectOne(new Organization() {

            });
            entity.setDeparth(parent.getDeparth() + "|" + entity.getOrgId());
        } else {
            entity.setDeparth(entity.getOrgId());
        }

        try {
            return this.organizationMapper.update(entity);
        } catch (Exception e) {
            this.logger.error("变更组织单位信息失败，原因：", e);
            throw new ServiceException("变更组织单位信息失败", e);
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public int delete(final Organization org) throws ServiceException {
        try {
            this.departmentMapper.delete(new Department() {

            });
            return this.organizationMapper.delete(org);
        } catch (Exception e) {
            this.logger.error("物理删除组织单位失败，原因：", e);
            throw new ServiceException("物理删除组织单位失败", e);
        }
    }

    @Override
    public List<Organization> gets(final List<String> orgIds) {
        return gets(new HashMap<String, Object>(1) {

        });
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public int discard(final List<String> orgIds, final String userId) throws ServiceException {
        return discard(new HashMap<String, Object>(3) {

        });
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public int delete(final List<String> orgIds) throws ServiceException {
        return delete(new HashMap<String, Object>(1) {

        });
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public int discard(final String orgId, final String userId) throws ServiceException {
        return discard(new HashMap<String, Object>(3) {

        });
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public int delete(final String orgId) throws ServiceException {
        return delete(new HashMap<String, Object>(1) {

        });
    }

    @Override
    public List<String> getLowerIds(String orgId) {
        Organization org = new Organization();
        org.setDeparth(orgId);
        org.setStatus(Integer.valueOf(StatusEnum.EFFECT.getCode()));
        List<Organization> list = list(org);
        if (CollectionUtils.isEmpty(list)) {
            return new ArrayList();
        }
        return (List) list.stream().map(Organization::getOrgId).collect(Collectors.toList());
    }

    @Override
    public List<String> getNotExistIds(final List<String> orgIds) {
        if (CollectionUtils.isEmpty(orgIds)) {
            return null;
        }
        List<Organization> list = gets(new HashMap<String, Object>(2) {

        });
        if (CollectionUtils.isEmpty(list)) {
            return orgIds;
        }

        Set<String> existIds = (Set) list.stream().map(Organization::getOrgId)
                .collect(Collectors.toSet());

        return (List) orgIds.stream().filter(s -> !existIds.contains(s)).collect(Collectors.toList());
    }


    private int delete(Map<String, Object> args) throws ServiceException {
        try {
            this.departmentMapper.remove(args);
            this.organizationMapper.remove(args);
        } catch (Exception e) {
            this.logger.error("物理删除组织单位失败，原因：", e);
            throw new ServiceException("物理删除组织单位失败", e);
        }

        return 1;
    }


    private int discard(Map<String, Object> args) throws ServiceException {
        try {
            this.departmentMapper.discard(args);
            this.organizationMapper.discard(args);
        } catch (Exception e) {
            this.logger.error("逻辑删除组织单位失败，原因：", e);
            throw new ServiceException("逻辑删除组织单位失败", e);
        }

        return 1;
    }


    @Override
    public Organization getTopOrganization() {
        List<Organization> organizations = this.organizationMapper.getTopOrg();
        return CollectionUtils.isNotEmpty(organizations) ? (Organization) organizations.get(0) : null;
    }

    @Override
    public Organization getTopOrgIgnoreIsLinkage() {
        List<Organization> organizations = this.organizationMapper.getTopOrg();
        if (CollectionUtils.isEmpty(organizations)) {
            return null;
        }
        Organization top = (Organization) organizations.get(0);

        if (top.getIsLinkage().shortValue() == 1) {
            Organization query = new Organization();
            query.setParentId(top.getOrgId());
            query.setIsLinkage(Short.valueOf((short) 0));
            List<Organization> res = this.organizationMapper.list(query);
            if (CollectionUtils.isNotEmpty(res)) {
                top = (Organization) res.get(0);
            }
        }
        return top;
    }

    @Override
    public Organization getIgnoreStatus(String orgId) {
        return (Organization) this.organizationMapper.selectByPrimaryKey(orgId);
    }

}
